package cn.clj.cell;

import java.util.ArrayList;

/**
 * clj 的 cell
 * */
public class CljCell {
    private CljCellType cljCellType;
    private Object cell;

    public CljCell(final CljCellType cljCellType, final Object cell) {
        this.cell = cell;
        this.cljCellType = cljCellType;
    }

    public CljCell(final CljCellType cljCellType) {
        this.cljCellType = cljCellType;
    }

    public CljCell() {

    }

    @Override
    public String toString() {
        switch (cljCellType) {
            case symbol:
                return cell.toString();
            case Clj_list:
                ArrayList<CljCell> lst = (ArrayList<CljCell>) cell;
                StringBuilder sb = new StringBuilder();
                sb.append("(");
                for (int i = 0; i < lst.size(); i++)
                {
                    if (i == lst.size() - 1) {
                        sb.append(lst.get(i).toString());
                    }
                    else {
                        sb.append(lst.get(i).toString() + " ");
                    }
                }
                sb.append(")");
                return sb.toString();
            case def:
                return "def";
            case let:
                return "let";
            case cond:
                return "cond";
            case conj:
                return "conj";
            case defn:
                return "defn";
            case last:
                return "last";
            case list:
                return "list";
            case set:
                return "set";
            case hash_table:
                return "hash_table";
            case loop:
                return "loop";
            case recur:
                return "recur";
            case apply:
                return "apply";
            case map:
                return "map";
            case cons:
                return "cons";
            case reduce:
                return "reduce";
            case eval:
                return "eval";
            case rest:
                return "rest";
            case first:
                return "first";
            case quote:
                return "'";
            case braces:
                ArrayList<CljCell> lst1 = (ArrayList<CljCell>) cell;
                StringBuilder sb1 = new StringBuilder();
                sb1.append("{");
                for (int i = 0; i < lst1.size(); i++)
                {
                    if (i == lst1.size() - 1) {
                        sb1.append(lst1.get(i).toString());
                    }
                    else {
                        sb1.append(lst1.get(i).toString() + " ");
                    }
                }
                sb1.append("}");
                return sb1.toString();
            case do_clj:
                return "do";
            case if_clj:
                return "if";
            case and_clj:
                return "&";
            case bracket:
                ArrayList<CljCell> lst2 = (ArrayList<CljCell>) cell;
                StringBuilder sb2 = new StringBuilder();
                sb2.append("[");
                for (int i = 0; i < lst2.size(); i++)
                {
                    if (i == lst2.size() - 1) {
                        sb2.append(lst2.get(i).toString());
                    }
                    else {
                        sb2.append(lst2.get(i).toString() + " ");
                    }
                }
                sb2.append("]");
                return sb2.toString();
            case unquote:
                return "~";
            case defmacro:
                return "defmacro";
            case number_clj:
                return cell.toString();
            case quote_list:
                return "`";
            case string_clj:
                return cell.toString();
            case unquote_list:
                return "~@";

            case addition:
                return "+";
            case subtraction:
                return "-";
            case multiplication:
                return "*";
            case division:
                return "/";

            case string_func:
                return "string";
            case number_func:
                return "number";
            case boolean_func:
                return "boolean";
            case date_func:
                return "date";
            case int_func:
                return "int";
            case long_func:
                return "long";
            case char_func:
                return "char";
            case short_func:
                return "short";
            case byte_func:
                return "byte";
            case double_func:
                return "double";
            case float_func:
                return "float";

            case and:
                return "and";
            case or:
                return "or";
            case equals_clj:
                return "=";
            case greater_than_clj:
                return ">";

            case less_than_clj:
                return "<";
            case greater_equals_clj:
                return ">=";
            case less_equals_clj:
                return "<=";
            case else_clj:
                return ":else";

            case lbracket:
                return "[";
            case rbracket:
                return "]";
            case lbraces:
                return "{";
            case rbraces:
                return "}";
            case lparen:
                return "(";
            case rparen:
                return ")";

            case is_nil:
                return "nil?";
            case not:
                return "not";

            case boolean_clj:
                return "boolean";
            case println:
                return "println";
        }

        return null;
    }

    public CljCellType getCljCellType() {
        return cljCellType;
    }

    public void setCljCellType(CljCellType cljCellType) {
        this.cljCellType = cljCellType;
    }

    public Object getCell() {
        return cell;
    }

    public void setCell(Object cell) {
        this.cell = cell;
    }

}
